﻿#include <iostream>
#include <thread>
#include <mutex>
using namespace std;
/*
单列模式：
类全局只有一个实例属性,定义只能进行一次
为了解决多线程中调用导致重复定义，使用call_once函数

call_once函数：
保证函数在多线程环境中只执行一次,只有第一个线程的调用成功，其他线程调用时直接返回
由一个once_flag结构体里面来记录是否被执行

注：call_once不能用在主线程上！编译报错
*/
class Log {
private:
	static std::once_flag logOnce;  // 一次性执行标志
	static Log* log;                // 单例指针
	// 仅是声明，只是为了编译期提供符合记录，所以真正定义在类外，在链接阶段分配内存
	// 对于其他静态变量(非类成员静态变量)，即是声明也是定义

	Log() = default;  //私有默认构造函数(显式要求编译器生成默认实现，提高易读性)
	~Log() = default; //私有析构函数

	// 初始化函数（无参）
	static void init() { log = new Log(); }

public:
	// 删除拷贝构造和赋值运算符
	// 不设置私有而是delete,明确告知编译器和其他开发者"该函数被明确禁止使用"
	Log(const Log&) = delete;
	Log& operator=(const Log&) = delete;

	// 获取单例实例
	static Log& getInstance() {
		std::call_once(logOnce, init);// 饿汉模式，在类需要时再定义
		//call_once(logOnec,[](){lon = new Log();});
		return *log;
	}

	// 日志打印方法
	void print_log(const std::string& error) {
		//__TIME__ 是C/C++语言中的一个​​预定义宏​​，它提供了代码​​被编译的时间​​信息
		std::cout << __TIME__ << " " << error << std::endl;
	}
};
//静态成员变量定义和初始化
std::once_flag Log::logOnce;
Log* Log::log = nullptr;

void outLog() {
	Log::getInstance().print_log("error");
}

int main6() {
	thread(outLog).join();
	thread(outLog).join();//这次不会触发init函数，因为已经执行过了
	return 0;
}